import QtQuick 2.0
import QtQuick.Controls 2.15
import QtQml.Models 2.15
import "view"
import "components"

Item {
    anchors.fill: parent

    signal browseClicked()
    signal installClicked()
    signal updateClicked()
    signal preDownloadClicked()
    signal startClicked()
    signal retryClicked()
    signal cancelConfirmed()
    signal cancelRejected()
    signal hdiffPatchClicked()
    signal repatchClicked()
    signal stopConfirmed()
    signal killWineServerClicked()
    signal checkSelfUpdateClicked()
    signal checkIntegrityClicked()
    signal checkStopClicked()

    readonly property int uiStateLoading: 1
    readonly property int uiStateInstall: 2
    readonly property int uiStateInstalling: 3
    readonly property int uiStateUpdating: 5
    readonly property int uiStateStart: 6
    readonly property int uiStateRetry: 7
    readonly property int uiStateHdiffPatch: 8
    readonly property int uiStatePatch: 9
    readonly property int uiStateRunning: 10
    readonly property int uiStateStarting: 11
    readonly property int uiStateStopping: 12
    readonly property int uiStateWrongDir: 13
    readonly property int uiStateChecking: 14

    property bool hasUpdate: false
    property bool hasPreDownload: false
    property int uiState: uiStateLoading
    property alias isLogVisible: buttonLog.checked
    property alias progressText: textProgress.text
    property alias progress: progressBar.value // 0..1

    function log(message) {
        textLog.append(message)
    }

    function clearLog() {
        textLog.text = ""
    }

    function showLog() {
        buttonLog.checked = true
    }

    function confirmCancelInstall() {
        dialogCancelInstall.open()
    }

    Image {
        id: imageBackground
        anchors.fill: parent
        fillMode: Image.PreserveAspectCrop
        source: "qrc:/bg/bg.jpg"
        visible: !settings.hideBackground
    }

    Text {
        id: textVersion
        text: qsTr("Game Version:") + "\n" + (installedVersion || "?")
        anchors.right: parent.right
        anchors.top: parent.top
        anchors.topMargin: block * 0.75
        anchors.rightMargin: block
        horizontalAlignment: Text.AlignRight
        font.pixelSize: block / 1.5
        visible: !imageBackground.visible
    }

    Outline {
        id: versionOutline
        source: textVersion
        visible: imageBackground.visible
    }


    Rectangle {
        border.color: "black"
        radius: space / 4
        color: "#E0F0F0F0"
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.top: parent.top
        anchors.bottom: buttonBar.top
        anchors.margins: space
        visible: isLogVisible

        Flickable {
            id: flickable
            anchors.fill: parent

            boundsBehavior: Flickable.DragAndOvershootBounds
            flickableDirection: Flickable.VerticalFlick

            ScrollBar.vertical: ScrollBar {
                id: flickScroll
            }

            TextArea.flickable: TextArea {
                id: textLog
                width: parent.width
                height: parent.height
                readOnly: true
                wrapMode: TextArea.Wrap
                persistentSelection: true
                bottomPadding: 0
                selectByMouse: true
                color: "black"
            }


            function append(text) {
                let value = textLog.text + text
                let endPos = flickable.contentHeight * (1.0 - flickable.visibleArea.heightRatio)
                let pos = flickable.contentY

                textLog.text = value

                if (pos === endPos) {
                    flickable.contentY = endPos
                } else {
                    flickable.contentY = pos
                }
            }
        }
    }

    Item {
        id: buttonBar

        height: block + space
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.bottom: parent.bottom

        ImageButton {
            id: buttonSettings
            anchors.left: parent.left
            anchors.margins: space
            icon: "settings"
            enabled: uiState != uiStateInstalling && uiState != uiStateUpdating
                && uiState != uiStateChecking && !isPreDownloading
            onClicked: popupSettingsMenu.open()
        }

        ImageButton {
            id: buttonLog
            anchors.left: buttonSettings.right
            anchors.margins: space
            icon: "log"
            checkable: true
            checked: true
        }

        Text {
            id: textStatus
            visible: progressBar.visible
            anchors.left: textProgress.left
            anchors.right: textProgress.right
            anchors.bottom: textProgress.top
            anchors.bottomMargin: space / 4

            text: isPreDownloading ? qsTr("Pre-downloading...")
                    : uiState == uiStateInstalling ? qsTr("Installing...")
                    : uiState == uiStateUpdating ? qsTr("Updating...")
                    : uiState == uiStateChecking ? qsTr("Checking...")
                    : ""
        }

        Outline {
            id: textStatusOutline
            source: textStatus
            visible: textStatus.visible
        }

        Text {
            id: textProgress
            visible: progressBar.visible
            anchors.left: progressBar.left
            anchors.right: progressBar.right
            anchors.bottom: progressBar.top
            anchors.bottomMargin: space / 2
            elide: Text.ElideRight
        }

        Outline {
            id: textProgressOutline
            source: textProgress
            visible: textProgress.visible
        }


        ProgressBar {
            id: progressBar
            visible: isPreDownloading || uiState == uiStateInstalling
                || uiState == uiStateUpdating  || uiState == uiStateChecking
            anchors.left: buttonLog.right
            anchors.right: buttonUpdate.visible ? buttonUpdate.left
                            : buttonBrowse.visible ? buttonBrowse.left
                            : buttonInstallUpdate.left
            anchors.bottom: parent.bottom
            anchors.margins: space
        }

        Button {
            id: buttonBrowse
            visible: uiState == uiStateInstall || uiState == uiStateWrongDir
            title: qsTr("Browse...")
            anchors.right: buttonInstallUpdate.left
            anchors.margins: space
            onClicked: browseClicked()
        }

        Button {
            id: buttonUpdate
            visible: hasUpdate && (uiState == uiStateStart || uiState == uiStatePatch) || hasPreDownload
            title: !hasPreDownload ? (qsTr("Update to") + " v" + availableVersion)
                    : isPreDownloading ? qsTr("Stop\nPre-Download")
                    : (qsTr("Pre-Download") + "\nv" + preDownloadVersion)
            anchors.right: buttonInstallUpdate.left
            anchors.margins: space
            onClicked: isPreDownloading ? cancelConfirmed()
                        : hasPreDownload ? preDownloadClicked() : updateClicked()
        }

        Button {
            id: buttonInstallUpdate
            title: uiState == uiStateInstall ? qsTr("Install")
                    : uiState == uiStateRetry ? qsTr("Retry")
                    : uiState == uiStateLoading ? qsTr("Loading...")
                    : uiState == uiStateInstalling ? qsTr("Cancel")
                    : uiState == uiStateUpdating ? qsTr("Cancel")
                    : uiState == uiStateStart ? (qsTr("Start") + (hasUpdate ? (" v" + localVersionLoader.version) : ""))
                    : uiState == uiStateHdiffPatch ? qsTr("Update")
                    : uiState == uiStatePatch ? qsTr("Patch")
                    : uiState == uiStateRunning ? qsTr("Stop")
                    : uiState == uiStateStarting ? qsTr("Starting...")
                    : uiState == uiStateStopping ? qsTr("Stopping...")
                    : uiState == uiStateWrongDir ? qsTr("Install")
                    : uiState == uiStateChecking ? qsTr("Cancel")
                    : ""
            anchors.right: parent.right
            anchors.margins: space
            enabled: uiState != uiStateLoading
                    && uiState != uiStateStarting
                    && uiState != uiStateStopping
                    && uiState != uiStateWrongDir
                    && (!isPreDownloading || (uiState != uiStateInstall && uiState != uiStatePatch))
            onClicked: uiState == uiStateInstall ? installClicked()
                    : uiState == uiStateInstalling ? confirmCancelInstall()
                    : uiState == uiStateUpdating ? confirmCancelInstall()
                    : uiState == uiStateStart ? startClicked()
                    : uiState == uiStateRetry ? retryClicked()
                    : uiState == uiStateHdiffPatch ? hdiffPatchClicked()
                    : uiState == uiStatePatch ? repatchClicked()
                    : uiState == uiStateRunning ? dialogStopClient.open()
                    : uiState == uiStateChecking ? checkStopClicked()
                    : undefined
        }
    }

    Dialog {
        id: dialogCancelInstall
        anchors.centerIn: parent
        title: window.title
        standardButtons: Dialog.Yes | Dialog.No
        modal: true
        focus: true

        Text {
            id: textDialog
            anchors.fill: parent
            text: qsTr("Some tasks are still running. Do you wish to stop them?")
        }

        onAccepted: cancelConfirmed()
        onRejected: cancelRejected()
    }

    Dialog {
        id: dialogStopClient
        anchors.centerIn: parent
        title: window.title
        standardButtons: Dialog.Yes | Dialog.No
        modal: true
        focus: true

        Text {
            anchors.fill: parent
            text: qsTr("Please use this only as emergency option.")
                  + "\n" + qsTr("Do you wish to terminate client?")
        }

        onAccepted: stopConfirmed()
    }

    Dialog {
        id: dialogFirstRun
        anchors.centerIn: parent
        title: window.title
        standardButtons: Dialog.Ok
        modal: true
        focus: true

        Text {
            anchors.fill: parent
            text: qsTr("The game is not meant to run on Linux. It may also break at any time.\nThere's absolutely no guarantee.")
        }

        Component.onCompleted: {
            if (settings.firstRun) {
                settings.firstRun = false
                dialogFirstRun.open()
            }
        }
    }

    Dialog {
        id: dialogAbout
        anchors.centerIn: parent
        title: window.title
        standardButtons: Dialog.Ok
        modal: true
        focus: true

        Row {
            anchors.fill: parent
            spacing: space

            Image {
                id: aboutIcon
                source: "qrc:/appicon/paimon-launcher.png"
            }

            Text {
                textFormat: Text.RichText
                onLinkActivated: Qt.openUrlExternally(link)
                text: "Original workaround project: <a href='" + patchRepo + "'>Dawn</a><br/>"
                      + "<a href='" + patchRepo + "/src/master/TROUBLESHOOTING.md'>Troubleshooting page</a><br/>"
                      + "<a href='" + patchRepo + "/src/master/TWEAKS.md'>Game Tweaks</a><br/>"
                      + "<br/><br/>"
                      + "<a href='https://notabug.org/loentar/paimon-launcher/releases'>Check for new versions of launcher here</a><br/><br/>"
                      + "For bug reports please visit <br/>"
                      + "<a href='https://notabug.org/loentar/paimon-launcher/issues'>Paimon Launcher Issues</a><br/><br/>"
                      + "Copyright © Loentar 2022"
            }
        }
    }

    Script {
        id: script

        function openWineConfig() {
            execScript('client-wrapper', 'wineconfig')
        }
    }

    Popup {
        id: popupSettingsMenu

        x: buttonSettings.x
        y: parent.height - buttonSettings.height - height - space
        width: block * 7
        height: block * 0.8 * listMenu.model.count
        padding: 0
        focus: true
        clip: true
        closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
        background: Rectangle {
            color: "lightgray"
            border.color: "black"
            radius: space / 4
        }

        ListView {
            id: listMenu
            interactive: false

            anchors.fill: parent
            model: ListModel {
                ListElement { name: "browse"; text: qsTr("Change Game location...") }
                ListElement { name: "hidebg"; text: qsTr("Hide background") }
                ListElement { name: "clearlog"; text: qsTr("Clear log") }
                ListElement { name: "speedup"; text: qsTr("Speedup downloads") }
                ListElement { name: "limitdl"; text: qsTr("Limit download speed") }
                ListElement { name: "repatch"; text: qsTr("Re-apply Wine patch") }
                ListElement { name: "killwine"; text: qsTr("Kill wineserver") }
                ListElement { name: "editwine"; text: qsTr("Edit wineconfig.sh") }
                ListElement { name: "integrity"; text: qsTr("Run integrity check...") }
                ListElement { name: "checkupdate"; text: qsTr("Check for Launcher updates at startup") }
                ListElement { name: "selfupdate"; text: qsTr("Check for Launcher updates now...") }
                ListElement { name: "about"; text: qsTr("About...") }
            }
            delegate: Button {
                checkBox: model.name === "speedup"
                          || model.name === "limitdl"
                          || model.name === "hidebg"
                          || model.name === "checkupdate"
                checked: (model.name === "speedup" && settings.multiConnections) ||
                         (model.name === "limitdl" && settings.limitDownload) ||
                         (model.name === "checkupdate" && settings.checkLauncherUpdatesAtStartup) ||
                         (model.name === "hidebg" && settings.hideBackground)
                title: model.text
                enabled: (model.name !== "repatch" && model.name !== "integrity") || !!installedVersion
                width: listMenu.width
                height: block * 0.8
                menu: true
                horizontalAlignment: Text.AlignLeft

                onClicked: {
                    popupSettingsMenu.close()

                    switch (model.name) {
                        case "browse":
                            browseClicked()
                            break
                        case "hidebg":
                            settings.hideBackground = !settings.hideBackground
                            break
                        case "clearlog":
                            clearLog()
                            break
                        case "limitdl":
                            settings.limitDownload = !settings.limitDownload
                            break
                        case "speedup":
                            settings.multiConnections = !settings.multiConnections
                            break
                        case "repatch":
                            repatchClicked()
                            break
                        case "killwine":
                            killWineServerClicked()
                            break
                        case "editwine":
                            script.openWineConfig()
                            break
                        case "integrity":
                            checkIntegrityClicked()
                            break
                        case "checkupdate":
                            settings.checkLauncherUpdatesAtStartup = !settings.checkLauncherUpdatesAtStartup
                            break
                        case "selfupdate":
                            checkSelfUpdateClicked()
                            break
                        case "about":
                            dialogAbout.open()
                            break
                    }
                }
            }
        }
    }
}
